home *** CD-ROM | disk | FTP | other *** search
/ Gekikoh Dennoh Club 5 / Gekikoh Dennoh Club Vol. 5 (Japan).7z / Gekikoh Dennoh Club Vol. 5 (Japan) (Track 01).bin / internet / xip / iijppp.lzh / src / chat.c < prev    next >
C/C++ Source or Header  |  1994-09-02  |  7KB  |  376 lines

  1. /*
  2.  *        Written by Toshiharu OHNO (tony-o@iij.ad.jp)
  3.  *
  4.  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
  5.  *
  6.  *  Most of codes are derived from chat.c by Karl Fox (karl@MorningStar.Com).
  7.  *
  8.  *    Chat -- a program for automatic session establishment (i.e. dial
  9.  *        the phone and log in).
  10.  *
  11.  *    This software is in the public domain.
  12.  *
  13.  *    Please send all bug reports, requests for information, etc. to:
  14.  *
  15.  *        Karl Fox <karl@MorningStar.Com>
  16.  *        Morning Star Technologies, Inc.
  17.  *        1760 Zollinger Road
  18.  *        Columbus, OH  43221
  19.  *        (614)451-1883
  20.  *
  21.  *  TODO:
  22.  *    o Support more UUCP compatible control sequences.
  23.  *    o Dialing shoud not block monitor process.
  24.  */
  25. #include "defs.h"
  26. #include <ctype.h>
  27. #include <sys/uio.h>
  28. #ifndef isblank
  29. #define    isblank(c)    ((c) == '\t' || (c) == ' ')
  30. #endif
  31. #include <sys/time.h>
  32. #include <fcntl.h>
  33. #include "timeout.h"
  34. #include "vars.h"
  35.  
  36. static int TimeoutSec;
  37. static int abort_next, timeout_next;
  38. static int numaborts;
  39. char *AbortStrings[50];
  40.  
  41. extern int ChangeParity(char *);
  42.  
  43. #define    MATCH    1
  44. #define    NOMATCH    0
  45. #define    ABORT    -1
  46.  
  47. static char *
  48. findblank(p, instring)
  49. char *p;
  50. int instring;
  51. {
  52.   if (instring) {
  53.     while (*p) {
  54.       if (*p == '\\') {
  55.     strcpy(p, p + 1);
  56.     if (!*p)
  57.       break;
  58.       } else if (*p == '"')
  59.     return(p);
  60.       p++;
  61.     }
  62.   } else {
  63.     while (*p) {
  64.       if (isblank(*p))
  65.     return(p);
  66.       p++;
  67.     }
  68.   }
  69.   return p;
  70. }
  71.  
  72. int
  73. MakeArgs(script, pvect)
  74. char *script;
  75. char **pvect;
  76. {
  77.   int nargs, nb;
  78.   int instring;
  79.  
  80.   nargs = 0;
  81.   while (*script) {
  82.     nb = strspn(script, " \t");
  83.     script += nb;
  84.     if (*script) {
  85.       if (*script == '"') {
  86.     instring = 1;
  87.     script++;
  88.     if (*script == '\0')
  89.       return(nargs);
  90.       } else
  91.     instring = 0;
  92.       *pvect++ = script;
  93.       nargs++;
  94.       script = findblank(script, instring);
  95.       if (*script)
  96.     *script++ = '\0';
  97.     }
  98.   }
  99.   *pvect = NULL;
  100.   return nargs;
  101. }
  102.  
  103. /*
  104.  *  \r    Carrige return character
  105.  *  \s  Space character
  106.  *  \n  Line feed character
  107.  *  \T  Telephone number (defined via `set phone'
  108.  *  \t  Tab character
  109.  */
  110. char *
  111. ExpandString(str, result, sendmode)
  112. char *str;
  113. char *result;
  114. int sendmode;
  115. {
  116.   int addcr = 0;
  117.  
  118.   if (sendmode)
  119.     addcr = 1;
  120.   while (*str) {
  121.     switch (*str) {
  122.     case '\\':
  123.       str++;
  124.       switch (*str) {
  125.       case 'c':
  126.     if (sendmode)
  127.       addcr = 0;
  128.     break;
  129.       case 'd':        /* Delay 2 seconds */
  130.         sleep(2); break;
  131.       case 'p':
  132.         usleep(250000); break;    /* Pause 0.25 sec */
  133.       case 'n':
  134.     *result++ = '\n'; break;
  135.       case 'r':
  136.     *result++ = '\r'; break;
  137.       case 's':
  138.     *result++ = ' '; break;
  139.       case 't':
  140.     *result++ = '\t'; break;
  141.       case 'P':
  142.     bcopy(VarAuthKey, result, strlen(VarAuthKey));
  143.     result += strlen(VarAuthKey);
  144.     break;
  145.       case 'T':
  146.     bcopy(VarPhone, result, strlen(VarPhone));
  147.     result += strlen(VarPhone);
  148.     break;
  149.       case 'U':
  150.     bcopy(VarAuthName, result, strlen(VarAuthName));
  151.     result += strlen(VarAuthName);
  152.     break;
  153.       default:
  154.     *result++ = *str; break;
  155.       }
  156.       if (*str) str++;
  157.       break;
  158.     case '^':
  159.       str++;
  160.       if (*str)
  161.     *result++ = *str++ & 0x1f;
  162.       break;
  163.     default:
  164.       *result++ = *str++;
  165.       break;
  166.     }
  167.   }
  168.   if (addcr)
  169.     *result++ = '\r';
  170.   *result++ = '\0';
  171.   return(result);
  172. }
  173.  
  174. int
  175. WaitforString(estr)
  176. char *estr;
  177. {
  178. #define    IBSIZE 200
  179.   struct timeval timeout;
  180.   char *s, *str, ch;
  181.   char *inp;
  182.   fd_set rfds;
  183.   int i, nfds;
  184.   char buff[200];
  185.   char inbuff[IBSIZE];
  186.  
  187.   (void) ExpandString(estr, buff, 0);
  188.   LogPrintf(LOG_CHAT, "Wait for (%d): %s --> %s\n", TimeoutSec, estr, buff);
  189.   str = buff;
  190.   inp = inbuff;
  191.  
  192.   nfds = modem + 1;
  193.   s = str;
  194.   for (;;) {
  195.     FD_ZERO(&rfds);
  196.     FD_SET(modem, &rfds);
  197.     /*
  198.      *  Because it is not clear whether select() modifies timeout value,
  199.      *  it is better to initialize timeout values everytime.
  200.      */
  201.     timeout.tv_sec = TimeoutSec;
  202.     timeout.tv_usec = 0;
  203.  
  204.     i = select(nfds, &rfds, NULL, NULL, &timeout);
  205. #ifdef notdef
  206.     TimerService();
  207. #endif
  208.     if (i < 0) {
  209.       perror("select");
  210.       return(NOMATCH);
  211.     } else if (i == 0) {     /* Timeout reached! */
  212.       LogPrintf(LOG_CHAT, "can't get (%d).\n", timeout.tv_sec);
  213.       return(NOMATCH);
  214.     }
  215.     if (FD_ISSET(modem, &rfds)) {    /* got something */
  216.       read(modem, &ch, 1);
  217.       *inp++ = ch;
  218.       if (ch == *s) {
  219.     s++;
  220.     if (*s == '\0') {
  221.       return(MATCH);
  222.     }
  223.       } else {
  224.     s = str;
  225.     if (inp == inbuff+ IBSIZE) {
  226.       bcopy(inp - 100, inbuff, 100);
  227.       inp = inbuff + 100;
  228.     }
  229.     for (i = 0; i < numaborts; i++) {    /* Look for Abort strings */
  230.       int len;
  231.       char *s1;
  232.  
  233.       s1 = AbortStrings[i];
  234.       len = strlen(s1);
  235.       if ((len <= inp - inbuff) && (strncmp(inp - len, s1, len) == 0)) {
  236.         LogPrintf(LOG_CHAT, "Abort: %s\n", s1);
  237.         return(ABORT);
  238.       }
  239.     }
  240.       }
  241.     }
  242.   }
  243. }
  244.  
  245. void
  246. SendString(str)
  247. char *str;
  248. {
  249.   char buff[200];
  250.  
  251.   if (abort_next) {
  252.     abort_next = 0;
  253.     ExpandString(str, buff, 0);
  254.     AbortStrings[numaborts++] = strdup(buff);
  255.   } else if (timeout_next) {
  256.     timeout_next = 0;
  257.     TimeoutSec = atoi(str);
  258.     if (TimeoutSec <= 0)
  259.       TimeoutSec = 30;
  260.   } else {
  261.     (void) ExpandString(str, buff, 1);
  262.     LogPrintf(LOG_CHAT, "sending: %s\n", buff);
  263.     write(modem, buff, strlen(buff));
  264.   }
  265. }
  266.  
  267. int
  268. ExpectString(str)
  269. char *str;
  270. {
  271.   char *minus;
  272.   int state;
  273.  
  274.   if (strcmp(str, "ABORT") == 0) {
  275.     ++abort_next;
  276.     return(MATCH);
  277.   }
  278.   if (strcmp(str, "TIMEOUT") == 0) {
  279.     ++timeout_next;
  280.     return(MATCH);
  281.   }
  282.   LogPrintf(LOG_CHAT, "Expecting %s\n", str);
  283.   while (*str) {
  284.     /*
  285.      *  Check whether if string contains sub-send-expect.
  286.      */
  287.     for (minus = str; *minus; minus++) {
  288.       if (*minus == '-') {
  289.     if (minus == str || minus[-1] != '\\')
  290.       break;
  291.       }
  292.     }
  293.     if (*minus == '-') {      /* We have sub-send-expect. */
  294.       *minus++ = '\0';
  295.       state = WaitforString(str);
  296.       if (state != NOMATCH)
  297.     return(state);
  298.       /*
  299.        * Can't get expect string. Sendout send part.
  300.        */
  301.       str = minus;
  302.       for (minus = str; *minus; minus++) {
  303.     if (*minus == '-') {
  304.       if (minus == str || minus[-1] != '\\')
  305.         break;
  306.     }
  307.       }
  308.       if (*minus == '-') {
  309.     *minus++ = '\0';
  310.     SendString(str);
  311.     str = minus;
  312.       } else {
  313.     SendString(str);
  314.     return(MATCH);
  315.       }
  316.     } else {
  317.       /*
  318.        *  Simple case. Wait for string.
  319.        */
  320.       return(WaitforString(str));
  321.     }
  322.   }
  323.   return(MATCH);
  324. }
  325.  
  326. int
  327. DoChat(script)
  328. char *script;
  329. {
  330.   char *vector[20];
  331.   char **argv;
  332.   int argc, n, state;
  333. #ifdef DEBUG
  334.   int i;
  335. #endif
  336.   
  337.   timeout_next = abort_next = 0;
  338.   for (n = 0; AbortStrings[n]; n++) {
  339.     free(AbortStrings[n]);
  340.     AbortStrings[n] = NULL;
  341.   }
  342.   numaborts = 0;
  343.  
  344.   bzero(vector, sizeof(vector));
  345.   n = MakeArgs(script, &vector);
  346. #ifdef DEBUG
  347.   logprintf("n = %d\n", n);
  348.   for (i = 0; i < n; i++)
  349.     logprintf("  %s\n", vector[i]);
  350. #endif
  351.   argc = n;
  352.   argv = vector;
  353.   TimeoutSec = 30;
  354.   while (*argv) {
  355.     if (strcmp(*argv, "P_ZERO") == 0 ||
  356.     strcmp(*argv, "P_ODD") == 0 || strcmp(*argv, "P_EVEN") == 0) {
  357.       ChangeParity(*argv++);
  358.       continue;
  359.     }
  360.     state = ExpectString(*argv++);
  361.     switch (state) {
  362.     case MATCH:
  363.       if (*argv)
  364.     SendString(*argv++);
  365.       break;
  366.     case ABORT:
  367. #ifdef notdef
  368.       HangupModem();
  369. #endif
  370.     case NOMATCH:
  371.       return(NOMATCH);
  372.     }
  373.   }
  374.   return(MATCH);
  375. }
  376.